package org.zecontech.extraplus.datagen;

import net.minecraft.core.HolderLookup;
import net.minecraft.core.registries.Registries;
import net.minecraft.data.PackOutput;
import net.minecraft.data.recipes.RecipeCategory;
import net.minecraft.data.recipes.RecipeOutput;
import net.minecraft.data.recipes.RecipeProvider;
import net.minecraft.data.recipes.SimpleCookingRecipeBuilder;
import net.minecraft.resources.ResourceKey;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.crafting.Ingredient;
import net.minecraft.world.level.ItemLike;
import net.minecraft.world.level.block.Blocks;
import org.zecontech.extraplus.ExtraPlus;
import org.zecontech.extraplus.init.ModBlocks;
import org.zecontech.extraplus.init.ModItems;
import org.zecontech.extraplus.util.Helpers;

import java.util.concurrent.CompletableFuture;

/**
 * 模组配方数据生成提供者
 */
public class ModRecipeProvider extends RecipeProvider {

    protected ModRecipeProvider(HolderLookup.Provider registries, RecipeOutput output) {
        super(registries, output);
    }

    /**
     * 构建生成配方
     */
    @Override
    protected void buildRecipes() {
        this.shaped(RecipeCategory.FOOD, ModItems.RUBY_APPLE)
                .define('#', Items.APPLE)
                .define('X', ModItems.RUBY)
                .pattern("XXX")
                .pattern("X#X")
                .pattern("XXX").unlockedBy("has_" + Helpers.getItemName(ModItems.RUBY),
                        this.has(ModItems.RUBY)).save(this.output);
        this.shapeless(RecipeCategory.FOOD, ModItems.CHENTAO)
                .requires(ModItems.RUBY, 1)
                .requires(Items.APPLE, 1)
                .unlockedBy("has_" + Helpers.getItemName(Items.APPLE),
                        this.has(Items.APPLE)).save(this.output);
        this.shapeless(RecipeCategory.FOOD, ModItems.NAILONG_JAR)
                .requires(ModItems.CHENTAO, 1)
                .requires(Items.MILK_BUCKET, 1)
                .requires(ModItems.KELONG_MEAT, 1)
                .unlockedBy("has_" + Helpers.getItemName(Items.MILK_BUCKET),
                        this.has(Items.MILK_BUCKET)).save(this.output);
        toolRecipes();
        armorsRecipes();
        storageRecipes();
        dyeRecipes();
        bricksBlockRecipes();
        woodRecipes();
        heatRecipes();
    }

    /**
     * 热处理合成
     */
    private void heatRecipes() {
        heatRecipe(ModBlocks.RUBY_ORE.get(), ModItems.RUBY);
        heatRecipe(ModBlocks.AMBER_ORE.get(), ModItems.AMBER);
        heatRecipe(ModItems.RUBY_APPLE, ModItems.COOKED_RUBY_APPLE);
        heatRecipe(Items.EGG, ModItems.FRIED_EGG);
    }

    /**
     * 工具合成
     */
    private void toolRecipes() {
        toolsRecipe(ModItems.RUBY, ModItems.RUBY_PICKAXE, ModItems.RUBY_AXE, ModItems.RUBY_SHOVEL, ModItems.RUBY_HOE, ModItems.RUBY_SWORD);
        toolsRecipe(ModItems.AMBER, ModItems.AMBER_PICKAXE, ModItems.AMBER_AXE, ModItems.AMBER_SHOVEL, ModItems.AMBER_HOE, ModItems.AMBER_SWORD);
        toolsRecipe(Items.EMERALD, ModItems.EMERALD_PICKAXE, ModItems.EMERALD_AXE, ModItems.EMERALD_SHOVEL, ModItems.EMERALD_HOE, ModItems.EMERALD_SWORD);
        toolsRecipe(ModItems.SILVER_INGOT, ModItems.SILVER_PICKAXE, ModItems.SILVER_AXE, ModItems.SILVER_SHOVEL, ModItems.SILVER_HOE, ModItems.SILVER_SWORD);
    }

    /**
     * 盔甲合成
     */
    private void armorsRecipes() {
        armorRecipe(ModItems.RUBY, ModItems.RUBY_HELMET, ModItems.RUBY_CHESTPLATE, ModItems.RUBY_LEGGINGS, ModItems.RUBY_BOOTS);
        armorRecipe(ModItems.AMBER, ModItems.AMBER_HELMET, ModItems.AMBER_CHESTPLATE, ModItems.AMBER_LEGGINGS, ModItems.AMBER_BOOTS);
        armorRecipe(Items.EMERALD, ModItems.EMERALD_HELMET, ModItems.EMERALD_CHESTPLATE, ModItems.EMERALD_LEGGINGS, ModItems.EMERALD_BOOTS);
        armorRecipe(ModItems.SILVER_INGOT, ModItems.SILVER_HELMET, ModItems.SILVER_CHESTPLATE, ModItems.SILVER_LEGGINGS, ModItems.SILVER_BOOTS);
    }

    /**
     * 存储合成
     */
    private void storageRecipes() {
        nineStorageLikeRecipe(ModItems.RUBY.get(), ModBlocks.RUBY_BLOCK.asItem());
        nineStorageLikeRecipe(ModItems.AMBER.get(), ModBlocks.AMBER_BLOCK.asItem());
        nineStorageLikeRecipe(ModItems.SILVER_INGOT.get(), ModBlocks.SILVER_BLOCK.asItem());
    }

    /**
     * 染料合成
     */
    private void dyeRecipes() {
        dyeRecipe(ModBlocks.PLANTAGO.get(), Items.YELLOW_DYE);
        dyeRecipe(ModBlocks.ACHILLEA_WHITE.get(), Items.WHITE_DYE);
        dyeRecipe(ModBlocks.ANAGALLIS_YELLOW.get(), Items.YELLOW_DYE);
        dyeRecipe(ModBlocks.ANTIRRHINUM.get(), Items.PINK_DYE);
        dyeRecipe(ModBlocks.CAMPANULA_BLUE.get(), Items.BLUE_DYE);
        dyeRecipe(ModBlocks.CENTAUREA.get(), Items.BLUE_DYE);
        dyeRecipe(ModBlocks.DIGITALIS_BLUE.get(), Items.BLUE_DYE);
        dyeRecipe(ModBlocks.DIGITALIS_YELLOW.get(), Items.YELLOW_DYE);
        dyeRecipe(ModBlocks.DOSERA.get(), Items.RED_DYE);
        dyeRecipe(ModBlocks.IRIS.get(), Items.PURPLE_DYE);
        dyeRecipe(ModBlocks.LEONTOPODIUM_WHITE.get(), Items.WHITE_DYE);
        dyeRecipe(ModBlocks.LEUCANTHEMUM_WHITE.get(), Items.WHITE_DYE);
        dyeRecipe(ModBlocks.MUSHROOM_AMANITA_GREEN.get(), Items.GREEN_DYE);
        dyeRecipe(ModBlocks.MUSHROOM_BOLETUS.get(), Items.BROWN_DYE);
        dyeRecipe(ModBlocks.MUSHROOM_CANTHARELLUS.get(), Items.YELLOW_DYE);
        dyeRecipe(ModBlocks.MUSHROOM_GALERINA.get(), Items.YELLOW_DYE);
        dyeRecipe(ModBlocks.MUSHROOM_GYROMITRA.get(), Items.PURPLE_DYE);
        dyeRecipe(ModBlocks.MUSHROOM_MACROLEPIOTA.get(), Items.BROWN_DYE);
        dyeRecipe(ModBlocks.PAPVER_RED.get(), Items.RED_DYE);
        dyeRecipe(ModBlocks.TRIFOLIUM_RED.get(), Items.RED_DYE);
        dyeRecipe(ModBlocks.TRIFOLIUM_WHITE.get(), Items.WHITE_DYE);
    }

    /**
     * 砖块合成
     */
    private void bricksBlockRecipes() {
        fourBlocksRecipe(Blocks.ICE, ModBlocks.ICE_BRICKS);
        fourBlocksRecipe(Blocks.SNOW_BLOCK, ModBlocks.SNOW_BRICKS);
    }

    /**
     * 木头合成
     */
    private void woodRecipes() {
        planksFromLogCustom(ModBlocks.WILLOW_PLANKS.get(), ModBlocks.WILLOW_LOG.get(), ModBlocks.WILLOW_WOOD.get());
        woodFromLogs(ModBlocks.WILLOW_WOOD.get(), ModBlocks.WILLOW_LOG.get());
    }

    /**
     *  原木合成木板
     * @param planks 木板
     * @param logs  原木
     */
    protected void planksFromLogCustom(ItemLike planks, ItemLike logs, ItemLike woods) {
        this.shapeless(RecipeCategory.BUILDING_BLOCKS, planks, 4).requires(logs).group("planks").unlockedBy("has_log", this.has(logs)).save(this.output);
        this.shapeless(RecipeCategory.BUILDING_BLOCKS, planks, 16).requires(woods).group("planks").unlockedBy("has_log", this.has(woods)).save(this.output, Helpers.identifier(Helpers.getItemName(planks) + "_from_" + Helpers.getItemName(woods)).toString());
    }

    /**
     * 四格方块合成
     * @param material 原材料
     * @param result 结果
     */
    private void fourBlocksRecipe(ItemLike material, ItemLike result) {
        this.shaped(RecipeCategory.MISC, result, 4)
                .define('#', material)
                .pattern("##")
                .pattern("##")
                .unlockedBy("has_" + Helpers.getItemName(material),
                        this.has(material)).save(this.output, Helpers.identifier(Helpers.getItemName(result) + "_from_" + Helpers.getItemName(material)).toString());
    }

    /**
     * 染料合成
     * @param material 原材料
     * @param result 结果
     */
    protected void dyeRecipe(ItemLike material, ItemLike result) {
        this.shapeless(RecipeCategory.MISC, result, 2)
                .requires(material)
                .unlockedBy("has_" + Helpers.getItemName(material),
                        this.has(material)).save(this.output, Helpers.identifier(Helpers.getItemName(result) + "_from_" + Helpers.getItemName(material)).toString());
    }

    /**
     * 工具合成
     * @param material 原材料
     * @param pickaxe 镐子
     * @param axe 斧头
     * @param shovel 铲子
     * @param hoe 锄头
     * @param sword 剑
     */
    private void toolsRecipe(ItemLike material, ItemLike pickaxe, ItemLike axe, ItemLike shovel, ItemLike hoe, ItemLike sword) {
        pickaxeRecipe(material, pickaxe);
        axeRecipe(material, axe);
        shovelRecipe(material, shovel);
        hoeRecipe(material, hoe);
        swordRecipe(material, sword);
    }

    /**
     * 九宫格存储合成
     * @param material 原材料
     * @param result 结果
     */
    private void nineStorageLikeRecipe(ItemLike material, ItemLike result) {
        this.shapeless(RecipeCategory.BUILDING_BLOCKS, material, 9).requires(result).unlockedBy(getHasName(result), this.has(result)).save(this.output, ResourceKey.create(Registries.RECIPE, Helpers.identifier(Helpers.getItemName(material) + "_from_" + Helpers.getItemName(result))));
        this.shaped(RecipeCategory.BUILDING_BLOCKS, result).define('#', material).pattern("###").pattern("###").pattern("###").unlockedBy(getHasName(material), this.has(material)).save(this.output, ResourceKey.create(Registries.RECIPE, Helpers.identifier(Helpers.getItemName(result) + "_from_" + Helpers.getItemName(material))));
    }

    /**
     * 盔甲配方生成
     * @param material 原材料
     * @param helmet 头盔
     * @param chestplate 胸甲
     * @param leggings 腿甲
     * @param boots 靴子
     */
    private void armorRecipe(ItemLike material, ItemLike helmet, ItemLike chestplate, ItemLike leggings, ItemLike boots) {
        this.shaped(RecipeCategory.COMBAT, helmet)
                .define('X', material)
                .pattern("XXX")
                .pattern("X X")
                .pattern("   ").unlockedBy("has_" + Helpers.getItemName(material),
                        this.has(material)).save(this.output);
        this.shaped(RecipeCategory.COMBAT, chestplate)
                .define('X', material)
                .pattern("X X")
                .pattern("XXX")
                .pattern("XXX").unlockedBy("has_" + Helpers.getItemName(material),
                        this.has(material)).save(this.output);
        this.shaped(RecipeCategory.COMBAT, leggings)
                .define('X', material)
                .pattern("XXX")
                .pattern("X X")
                .pattern("X X").unlockedBy("has_" + Helpers.getItemName(material),
                        this.has(material)).save(this.output);
        this.shaped(RecipeCategory.COMBAT, boots)
                .define('X', material)
                .pattern("   ")
                .pattern("X X")
                .pattern("X X").unlockedBy("has_" + Helpers.getItemName(material),
                        this.has(material)).save(this.output);
    }

    /**
     * 镐子配方生成
     * @param material 原材料
     * @param result 镐子
     */
    private void pickaxeRecipe(ItemLike material, ItemLike result){
        this.shaped(RecipeCategory.TOOLS, result)
                .define('#', Items.STICK)
                .define('X', material)
                .pattern("XXX")
                .pattern(" # ")
                .pattern(" # ").unlockedBy("has_" + Helpers.getItemName(material),
                        this.has(material)).save(this.output);
    }

    /**
     * 斧头配方生成
     * @param material 原材料
     * @param result 斧头
     */
    private void axeRecipe(ItemLike material, ItemLike result){
        this.shaped(RecipeCategory.TOOLS, result)
                .define('#', Items.STICK)
                .define('X', material)
                .pattern("XX ")
                .pattern("X# ")
                .pattern(" # ").unlockedBy("has_" + Helpers.getItemName(material),
                        this.has(material)).save(this.output);
    }

    /**
     * 铲子配方生成
     * @param material 原材料
     * @param result 铲子
     */
    private void shovelRecipe(ItemLike material, ItemLike result){
        this.shaped(RecipeCategory.TOOLS, result)
                .define('#', Items.STICK)
                .define('X', material)
                .pattern(" X ")
                .pattern(" # ")
                .pattern(" # ").unlockedBy("has_" + Helpers.getItemName(material),
                        this.has(material)).save(this.output);
    }

    /**
     * 锄头配方生成
     * @param material 原材料
     * @param result 锄头
     */
    private void hoeRecipe(ItemLike material, ItemLike result){
        this.shaped(RecipeCategory.TOOLS, result)
                .define('#', Items.STICK)
                .define('X', material)
                .pattern("XX ")
                .pattern(" # ")
                .pattern(" # ").unlockedBy("has_" + Helpers.getItemName(material),
                        this.has(material)).save(this.output);
    }

    /**
     * 剑配方生成
     * @param material 原材料
     * @param result 剑
     */
    private void swordRecipe(ItemLike material, ItemLike result){
        this.shaped(RecipeCategory.COMBAT, result)
                .define('#', Items.STICK)
                .define('X', material)
                .pattern(" X " )
                .pattern(" X ")
                .pattern(" # ").unlockedBy("has_" + Helpers.getItemName(material),
                        this.has(material)).save(this.output);
    }

    /**
     * 加热配方生成
     * @param material 原材料
     * @param result 成品
     */
    private void heatRecipe(ItemLike material, ItemLike result) {
        SimpleCookingRecipeBuilder.smelting(Ingredient.of(material),
                RecipeCategory.REDSTONE, result,
                0.35F, 200).unlockedBy("has_" + Helpers.getItemName(material),
                this.has(material)).save(this.output, ExtraPlus.MOD_ID + ":" + Helpers.getItemName(result) + "_from_smelting");
        SimpleCookingRecipeBuilder.blasting(Ingredient.of(material),
                RecipeCategory.REDSTONE, result,
                0.35F, 200).unlockedBy("has_" + Helpers.getItemName(material),
                this.has(material)).save(this.output, ExtraPlus.MOD_ID + ":" + Helpers.getItemName(result) + "_from_blasting");
        SimpleCookingRecipeBuilder.campfireCooking(Ingredient.of(material),
                RecipeCategory.REDSTONE, result,
                0.35F, 200).unlockedBy("has_" + Helpers.getItemName(material),
                this.has(material)).save(this.output, ExtraPlus.MOD_ID + ":" + Helpers.getItemName(result) + "_from_campfire");
        SimpleCookingRecipeBuilder.smoking(Ingredient.of(material),
                RecipeCategory.REDSTONE, result,
                0.35F, 200).unlockedBy("has_" + Helpers.getItemName(material),
                this.has(material)).save(this.output, ExtraPlus.MOD_ID + ":" + Helpers.getItemName(result) + "_from_smoking");
    }

    /**
     * 配方数据生成运行者
     */
    public static class Runner extends RecipeProvider.Runner {

        public Runner(PackOutput output, CompletableFuture<HolderLookup.Provider> lookupProvider) {
            super(output, lookupProvider);
        }

        /**
         * 创建配方生成器运行
         * @param provider 提供者
         * @param output 导出
         * @return 配方提供者
         */
        @Override
        protected RecipeProvider createRecipeProvider(HolderLookup.Provider provider, RecipeOutput output) {
            return new ModRecipeProvider(provider, output);
        }

        /**
         * 数据运行名字
         * @return 字符串
         */
        @Override
        public String getName() {
            return "ExtraPlus";
        }
    }
}